package com.apexedu.biz.service.impl;

import com.apexedu.biz.Const;
import com.apexedu.biz.action.TimerAction;
import com.apexedu.biz.entity.TTimer;
import com.apexedu.biz.entity.TTimerLog;
import com.apexedu.biz.timer.TimerMap;
import com.apexedu.framework.service.impl.AbstractBaseServiceSupport;
import com.apexedu.framework.util.DBUtil;
import com.apexedu.framework.util.Pager;
import com.apexedu.framework.util.SeqFactory;
import com.apexedu.identity.action.IdLoginAction;
import com.apexedu.sys.SysConstants;
import com.apexedu.sys.util.BusinessLogUtil;
import com.apexedu.util.DateUtil;
import com.apexedu.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 定时器设置
 * Created by ly on 2014/12/2.
 */
@Component("timerService")
public class TimerServiceImpl extends AbstractBaseServiceSupport {
    protected Log log = LogFactory.getLog(this.getClass());//日志记录

    /**
     * 初始化所有启用的定时器
     */
    @PostConstruct
    @Transactional
    public void init() {
        Timer timer = new Timer();
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, 1); //启动后1分钟后开启
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                List<TTimer> list = baseDao.findByHql(" from TTimer where state='1'");
                for (TTimer timer : list) {
                    doTimer(timer, true);
                }
            }
        }, cal.getTime());
    }

    @Override
    public List<?> list(Object myaction, Pager pager) throws Exception {
        String sql = "select a.wid,timername, (select zdmc from T_Sys_Code where zdlb='timer_code' and zdbm=a.timercode)," +
                " starttime,(select zdmc from T_Sys_Code where zdlb='timer_jgsj' and zdbm=a.intervaltype)," +
                "interval,a.state as state,b.lasttime,b.executesecond,b.nexttime,b.state as st,b.errorlog" +
                " from T_Timer a left join t_timer_log b on a.wid=b.tid and b.state>=0 order by wid desc";
        return DBUtil.queryAllBeanList(sql, TTimer.class);
    }

    @Override
    public void load(Object myaction) throws Exception {
        TimerAction action = (TimerAction) myaction;
        String id = action.getWid();
        TTimer timer = getBaseDao().findById(TTimer.class, id);
        action.setTimer(timer);
    }

    @Override
    public boolean remove(Object myaction) throws Exception {
        TimerAction action = (TimerAction) myaction;
        String ids = action.getWid();
        List<TTimer> list = baseDao.findByHql(" from TTimer where wid in ('" + ids.replaceAll(",", "','") + "')");
        for (TTimer timer : list) {
            doTimer(timer, false);
        }
        boolean deleteSuccess = getBaseDao().deleteAll("TTimer", "wid", "=", ids);
        if (deleteSuccess) {
            BusinessLogUtil.log(action.getUserloginid(), SysConstants.CZDX_T_TIMER, Const.LOG_ACTION_DEL, IdLoginAction.getIpAddr(action.getRequest()), "移除定时器");
        }
        return deleteSuccess;
    }

    @Override
    public String changeState(Object myaction) throws Exception {
        TimerAction action = (TimerAction) myaction;
        String state = action.getRequest().getParameter("shzt");
        String ids = action.getWid();
        List<TTimer> list = baseDao.findByHql(" from TTimer where wid in ('" + ids.replaceAll(",", "','") + "')");
        for (TTimer timer : list) {
            doTimer(timer, "1".equals(state));
        }
        if (DBUtil.executeSQL("update t_timer set state = ? where wid in ('" + ids.replaceAll(",", "','") + "')", state) > 0) {
            return "操作成功";
        } else {
            return "操作失败";
        }
    }

    @Override
    public void saveOrUpdate(Object myaction) throws Exception {
        TimerAction action = (TimerAction) myaction;
        TTimer timer = action.getTimer();
        String sql = "from t_timer where timercode = ?";
        if (StringUtil.isNotBlank(timer.getWid())) {
            sql += " and wid != '" + timer.getWid() + "'";
        }
        long c = DBUtil.count(sql, timer.getTimercode());
        if (c > 0) {
            throw new Exception("该定时器编码已使用");
        }
        if (StringUtil.isBlank(timer.getWid())) {
            timer.setWid(SeqFactory.getNewSequenceAlone());
            getBaseDao().save(timer);
            BusinessLogUtil.log(action.getLoginuser().getUserloginid(), SysConstants.CZDX_T_TIMER, Const.LOG_ACTION_SAVE, IdLoginAction.getIpAddr(action.getRequest()));
        } else {
            getBaseDao().updateNotNull(timer);
            BusinessLogUtil.log(action.getLoginuser().getUserloginid(), SysConstants.CZDX_T_TIMER, Const.LOG_ACTION_UPDATE, IdLoginAction.getIpAddr(action.getRequest()));
        }
        doTimer(timer, "1".equals(timer.getState()));
    }

    /**
     * 开启/关闭定时器
     *
     * @param t     定时器设置
     * @param state true 启用| false 禁用
     */
    private void doTimer(TTimer t, boolean state) {
        Timer timer = TimerMap.get(t.getTimercode());
        if (timer != null) {
            timer.cancel();
        }
        try {
            if (state) {
                timer = new Timer();
                TimerMap.put(t.getTimercode(), timer);
                int ms = 1000 * t.getInterval().intValue();
                if ("m".equals(t.getIntervaltype())) {
                    ms *= 60;
                } else if ("h".equals(t.getIntervaltype())) {
                    ms *= 60 * 60;
                } else if ("d".equals(t.getIntervaltype())) {
                    ms *= 60 * 60 * 24;
                }


                Class class_ = Class.forName("com.apexedu.biz.timer." + t.getTimercode() + "Task");
                Calendar cal = Calendar.getInstance();


                String dbtime = DBUtil.queryField("select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual");
                Date dbtime_d = DateUtil.parseDate(dbtime);
                Date statetime = t.getStarttime();
                if(dbtime_d.getTime()-cal.getTimeInMillis()>1000*3600){
                }

                if (t.getStarttime().getTime() >= cal.getTimeInMillis()) {
                    TTimerLog timerLog = new TTimerLog(-1);
                    timerLog.setTid(t.getWid());
                    timerLog.setNexttime(t.getStarttime());
                    DBUtil.executeSQL("update t_timer_log set state='-1' where tid = ?", t.getWid());
                    baseDao.save(timerLog);
                }
                timer.schedule((TimerTask) class_.newInstance(), t.getStarttime(), ms);
            } else {
                DBUtil.executeSQL("update t_timer_log set state='-1' where tid = ?", t.getWid());
            }
        } catch (Exception e) {
            log.error("doTimer error : " + e);
            throw new RuntimeException(e);
        }
    }
}
